package com.oron3.bouncer.interaction;

import java.util.ArrayList;
import java.util.HashMap;




public class InteractionInterpreter {
	private final ArrayList<MotionListener> motionListeners = new ArrayList<MotionListener>(0);
	private final HashMap<InteractiveEvent,InteractiveTask> runIfNotConsumed = new HashMap<InteractiveEvent,InteractiveTask>();
	private final Repainter mRepainter;
	private final InteractiveEvent dummy = new InteractiveEvent(this);
	public InteractionInterpreter(final Repainter rep) {
		mRepainter = rep;
	}
	public void addListener(final Object listener) {
		if (listener instanceof MotionListener)
			addMotionListener((MotionListener) listener);
		if (listener instanceof PressListener)
			addPressListener((PressListener) listener);
		if (listener instanceof ClickListener)
			addClickListener((ClickListener) listener);
		if (listener instanceof ZoomListener)
			addZoomListener((ZoomListener) listener);
	}
	public void addMotionListener(final MotionListener listener) {
		if (motionListeners.contains(listener)) return;
		motionListeners.add(listener);
	}
	public void removeMotionListener(final MotionListener listener) {
		motionListeners.remove(listener);
	}
	/**
	 * Broadcasting movement event
	 */
	public void onMovement(final MotionEvent event) {
		boolean repaint = false;
		for (final MotionListener l : motionListeners) 
			repaint |= l.onMovement(event);
		finish(repaint,event);
	}
	private void finish(final boolean repaint, final InteractiveEvent event) {
		if (repaint) {
			runIfNotConsumed.remove(event);
			mRepainter.repaint();
		} else {
			final InteractiveTask runnable = runIfNotConsumed.remove(event);
			if (runnable!=null) 
				if (runnable.doTask())
					mRepainter.repaint();
		}
	}
	public void onDrag(final MotionEvent event) {
		boolean repaint = false;
		for (final MotionListener l : motionListeners) 
			repaint |= l.onDrag(event);
		finish(repaint,event);
	}

	private final ArrayList<ClickListener> clickListeners = new ArrayList<ClickListener>(0);

	public void addClickListener(final ClickListener listener) {
		if (clickListeners.contains(listener)) return;
		clickListeners.add(listener);
	}
	public void removeClickListener(final ClickListener listener) {
		clickListeners.remove(listener);
	}
	/**
	 * Broadcasting events
	 */
	public void onClick(final ClickEvent event) {
		boolean repaint = false;
		for (final ClickListener l : clickListeners) 
			repaint |= l.onClick(event);
		finish(repaint,event);
	}
	public void onDoubleClick(final ClickEvent event) {
		boolean repaint = false;
		for (final ClickListener l : clickListeners) 
			repaint |= l.onDoubleClick(event);
		finish(repaint,event);
	}
	private final ArrayList<PressListener> pressListeners = new ArrayList<PressListener>(0);

	public void addPressListener(final PressListener listener) {
		if (pressListeners.contains(listener)) return;
		pressListeners.add(listener);
	}
	public void removePressListener(final PressListener listener) {
		pressListeners.remove(listener);
	}
	/**
	 * Broadcasting events
	 */
	public void onPress(final InteractiveEvent event) {
		boolean repaint = false;
		for (final PressListener l : pressListeners) 
			repaint |= l.onPress(event);
		finish(repaint,event);
	}
	private final ArrayList<ZoomListener> listeners = new ArrayList<ZoomListener>(0);


	public void addZoomListener(final ZoomListener listener) {
		if (listeners.contains(listener)) return;
		listeners.add(listener);
	}
	public void removeZoomListener(final ZoomListener listener) {
		listeners.remove(listener);
	}
	/**
	 * Broadcasting events
	 * @return 
	 */
	public void onZoom(final ZoomEvent event) {
		boolean repaint = false;
		for (final ZoomListener l : listeners) 
			repaint |= l.onZoom(event);
		finish(repaint,event);
	}
	public void onDragEnd(final InteractiveEvent interactiveEvent) {
		boolean repaint = false;
		for (final MotionListener l : motionListeners) 
			repaint |= l.onDragEnd(interactiveEvent);
		finish(repaint,interactiveEvent);
	}

	public void onDragEnd() {
		boolean repaint = false;
		for (final MotionListener l : motionListeners) 
			repaint |= l.onDragEnd(dummy);
		finish(repaint,dummy);
	}
	public void runIfNotConsumed(final InteractiveEvent interactiveEvent,final InteractiveTask what) {
		runIfNotConsumed.put(interactiveEvent, what);
	}
	public void onRelease(final InteractiveEvent interactiveEvent) {
		boolean repaint = false;
		for (final PressListener l : pressListeners) 
			repaint |= l.onRelease(interactiveEvent);
		finish(repaint,interactiveEvent);
	}
}
